package org.lee.netty.task;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * NettyServerHandler
 * 服务器处理器
 * 说明：
 * 1、定义一个Handler，需要继承netty规定好的某个HandlerAdapter
 * 2、这时自定义一个Handler，才能称为一个Handler
 *
 * @author dralee
 * @date 2022-01-01 16:58:24
 **/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    // 数据读取完毕
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // writeAndFlush 是write+flush
        // 将数据写入到缓存，并刷新
        // 一般讲，对发送的数据进行编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端~ (>^ω^<)喵~1".getBytes(StandardCharsets.UTF_8)));
    }

    // 处理异常，一般是要关闭通道
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }

    // 读取数据实际（这里可读取客户端发送的消息）
    // 1、ChannelHandlerContext ctx上下文对象，含有管道pipeline，通道channel，地址
    // 2、Object msg：就是客户端发送的数据 默认Object
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 如比这里有一个非常耗时长的业务->异步执行->提交该channel对应NIOEventLoop的taskQueue中
        // 解决方案1 用户程序自定义的普通任务

        ctx.channel().eventLoop().execute(() -> {
            try {
                Thread.sleep(10 * 1000);
                ctx.writeAndFlush(Unpooled.copiedBuffer((DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + " hello, 客户端~ (>^ω^<)喵~2").getBytes(StandardCharsets.UTF_8)));
            } catch (Exception e) {
                System.out.println("发生异常" + e.getMessage());
            }
        });
        ctx.channel().eventLoop().execute(() -> {
            try {
                Thread.sleep(20 * 1000);
                ctx.writeAndFlush(Unpooled.copiedBuffer((DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + " hello, 客户端~ (>^ω^<)喵~3").getBytes(StandardCharsets.UTF_8)));
            } catch (Exception e) {
                System.out.println("发生异常" + e.getMessage());
            }
        });
        /* 在第一个任务结束后，再继续等待20秒后才运行第2个任务（因为是同一线程，所以后面的任务是在前一任务基础上再休xx秒）
        client: ChannelHandlerContext(NettyClientHandler#0, [id: 0x9ae69ce6, L:/127.0.0.1:8942 - R:/127.0.0.1:6668])
        服务器回复的消息：hello, 客户端~ (>^ω^<)喵~1
        服务器的地址：/127.0.0.1:6668
        服务器回复的消息：2022-01-03 17:18:19 hello, 客户端~ (>^ω^<)喵~2
        服务器的地址：/127.0.0.1:6668
        服务器回复的消息：2022-01-03 17:18:39 hello, 客户端~ (>^ω^<)喵~3
        服务器的地址：/127.0.0.1:6668
        */

        // 解决方案2 用户自定义定时任务 -> 该任务是提交到scheduleTaskQueue中
        ctx.channel().eventLoop().schedule(() -> {
            try {
                Thread.sleep(5 * 1000);
                ctx.writeAndFlush(Unpooled.copiedBuffer((DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + " hello, 客户端~ (>^ω^<)喵~4").getBytes(StandardCharsets.UTF_8)));
            } catch (Exception e) {
                System.out.println("发生异常" + e.getMessage());
            }
        }, 5, TimeUnit.SECONDS);

        //

        System.out.println("go on...");
        //        System.out.println("服务器读取线程：" + Thread.currentThread().getName());
//        System.out.println("server ctx:" + ctx);
//        System.out.println("channel与pipeline关系");
//        Channel channel = ctx.channel();
//        ChannelPipeline pipeline = channel.pipeline(); // 本质是一个双向链表，出栈入栈
//        // 将msg转成一个ByteBuffer
//        // ByteBuf是Netty提供的，不是NIO的ByteBuffer
//        ByteBuf buffer = (ByteBuf) msg;
//        System.out.println("客户端发送消息是：" + buffer.toString(StandardCharsets.UTF_8));
//        System.out.println("客户端地址：" + ctx.channel().remoteAddress());
    }
}
